using System;
using System.Net;
using System.Net.Mail;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
namespace APP.HELPER.Utils.Net
{
    public delegate void ThuEventHandler();
    public delegate void ConnectEventHandler(object sender, string Server, int Port);
    public delegate void DisconnectEventHandler(object sender, string Server);
    public delegate void AuthenticateEventHandler(object sender, string userName);
    public delegate void ConnectToInternetEventHandler(object sender);
    public delegate void DataTransferEventHandler(object sender);
    public delegate void ErrorEmailSentEventHandler(object sender, int Number, string Message);
    public delegate void SendProcessEventHandler(object sender, int Value, int Maxvalue);
    public delegate void SuccessEventHandler(object sender);

	public class SmtpClient2
	{
		private string smtpServer;
		private int smtpPort;
		private MailMessage2 mailMessage;
		private int timeOut;
		private string userName;
		private string password;
		private string errorMessage;
		private int ErrorNumber;
		private int Maxvalue;
		private Socket tcp_Socket;
		private NetworkStream networkStream;
		private SslStream secureStream;
		public event ThuEventHandler thu;
		public event ConnectEventHandler ConnectionEstablishing;
		public event ConnectEventHandler ConnectionEstablished;
		public event DisconnectEventHandler Disconnected;
		public event AuthenticateEventHandler AuthenticationBegan;
		public event AuthenticateEventHandler AuthenticationFinished;
		public event DataTransferEventHandler StartedDataTransfer;
		public event DataTransferEventHandler EndedDataTransfer;
		public event SuccessEventHandler Successes;
		public event ErrorEmailSentEventHandler ErrorEmailSent;
		public event ConnectToInternetEventHandler ConnectToInternet;
		public event SendProcessEventHandler SendProcess;
        

		public string SmtpServer
		{
			get
			{
				return this.smtpServer;
			}
			set
			{
				this.smtpServer = value;
			}
		}
		public int SmtpPort
		{
			get
			{
				return this.smtpPort;
			}
			set
			{
				this.smtpPort = value;
			}
		}
		public int TimeOut
		{
			get
			{
				return this.timeOut;
			}
			set
			{
				this.timeOut = value;
			}
		}
		public string UserName
		{
			get
			{
				return this.userName;
			}
			set
			{
				this.userName = value;
			}
		}
		public string Password
		{
			get
			{
				return this.password;
			}
			set
			{
				this.password = value;
			}
		}
		public int vError
		{
			get
			{
				return this.ErrorNumber;
			}
		}
		public SmtpClient2()
		{
			this.SmtpServer = "";
			this.smtpPort = 25;
			this.timeOut = 60;
			this.userName = "";
			this.password = "";
			this.errorMessage = "";
			this.ErrorNumber = 0;
			this.Maxvalue = 12;
		}
		public SmtpClient2(string server)
		{
			this.smtpServer = server;
			this.smtpPort = 25;
			this.timeOut = 60;
			this.userName = "";
			this.password = "";
			this.errorMessage = "";
			this.ErrorNumber = 0;
			this.Maxvalue = 12;
		}
		public SmtpClient2(string server, int port)
		{
			this.smtpServer = server;
			this.smtpPort = port;
			this.timeOut = 60;
			this.userName = "";
			this.password = "";
			this.errorMessage = "";
			this.ErrorNumber = 0;
			this.Maxvalue = 12;
		}
		private void RaiseConnectionEstablishing(string smtpServer, int smtpPort)
		{
			if (this.ConnectionEstablishing != null)
			{
				this.ConnectionEstablishing(this, smtpServer, smtpPort);
			}
		}
		private void RaiseSendProcess(int Value, int Maxvalue)
		{
			if (this.SendProcess != null)
			{
				this.SendProcess(this, Value, Maxvalue);
			}
		}
		private void RaiseConnectionEstablished(string smtpServer, int smtpPort)
		{
			if (this.ConnectionEstablished != null)
			{
				this.ConnectionEstablished(this, smtpServer, smtpPort);
			}
		}
		private void RaiseDisconnected(string smtpServer)
		{
			if (this.Disconnected != null)
			{
				this.Disconnected(this, smtpServer);
			}
		}
		private void RaiseAuthenticationBegan(string userName)
		{
			if (this.AuthenticationBegan != null)
			{
				this.AuthenticationBegan(this, userName);
			}
		}
		private void RaiseAuthenticationFinished(string userName)
		{
			if (this.AuthenticationFinished != null)
			{
				this.AuthenticationFinished(this, userName);
			}
		}
		private void RaiseStartedDataTransfer()
		{
			if (this.StartedDataTransfer != null)
			{
				this.StartedDataTransfer(this);
			}
		}
		private void RaiseEndedDataTransfer()
		{
			if (this.EndedDataTransfer != null)
			{
				this.EndedDataTransfer(this);
			}
		}
		private void RaiseSuccesses()
		{
			if (this.Successes != null)
			{
				this.Successes(this);
			}
		}
		private void RaiseErrorEmailSent(int Number, string Message)
		{
			if (this.ErrorEmailSent != null)
			{
				this.ErrorEmailSent(this, Number, Message);
			}
		}
		private void RaiseConnectToInternet()
		{
			if (this.ConnectToInternet != null)
			{
				this.ConnectToInternet(this);
			}
		}
		private void RaiseThuEventHandler()
		{
			if (this.thu != null)
			{
				this.thu();
			}
		}
		public void SendMail(MailMessage2 mailMessage)
		{
			this.RaiseSendProcess(0, this.Maxvalue);
			bool flag = false;
			while (!flag)
			{
				this.RaiseConnectToInternet();
				if (Internet.IsConnectedToInternet())
				{
					flag = true;
				}
				else
				{
					this.ErrorEmailSent(this, 0, "Can't connect to internet....");
					Thread.SpinWait(60000);
				}
			}
			this.RaiseSendProcess(1, this.Maxvalue);
			this.mailMessage = mailMessage;
			this.ErrorNumber = 0;
			this.tcp_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
			IPAddress[] hostAddresses;
			try
			{
				hostAddresses = Dns.GetHostAddresses(this.smtpServer);
				this.RaiseSendProcess(2, this.Maxvalue);
			}
			catch (Exception)
			{
				this.ErrorNumber = 1;
				this.errorMessage = "Smtp server \"" + this.smtpServer + "\" does not exist.";
				this.RaiseErrorEmailSent(1, this.errorMessage);
				return;
			}
			IPEndPoint remoteEP = new IPEndPoint(hostAddresses[0], this.SmtpPort);
			this.RaiseConnectionEstablishing(this.smtpServer, this.smtpPort);
			try
			{
				this.tcp_Socket.Connect(remoteEP);
				this.RaiseSendProcess(3, this.Maxvalue);
			}
			catch
			{
				this.ErrorNumber = 1;
				this.errorMessage = string.Concat(new object[]
				{
					"Unable to connect to SMTP server: ",
					this.smtpServer,
					",on port ",
					this.smtpPort,
					"."
				});
				this.RaiseErrorEmailSent(2, this.errorMessage);
			}
			this.networkStream = new NetworkStream(this.tcp_Socket);
			string text = "";
			string[] array = new string[]
			{
				"EHLO",
				"MAIL FROM:",
				"RCPT TO:",
				"DATA",
				"",
				"QUIT"
			};
			string[] array2 = new string[]
			{
				"250",
				"250",
				"250",
				"354",
				"250",
				"221"
			};
			bool flag2 = false;
			ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();
			if (!this.WaitForResponse("220", ref text, true))
			{
				this.errorMessage = "Did not get welcome message from SMTP server: " + this.smtpServer + ".\r\nServer said: " + text;
				this.tcp_Socket.Close();
				this.ErrorNumber = 1;
				this.RaiseErrorEmailSent(3, this.errorMessage);
			}
			else
			{
				this.RaiseSendProcess(4, this.Maxvalue);
				this.RaiseConnectionEstablished(this.smtpServer, this.smtpPort);
				for (int i = 0; i < array.Length; i++)
				{
					string text2 = array[i];
					this.RaiseSendProcess(4 + i + 1, this.Maxvalue);
					switch (i)
					{
					case 0:
						text2 = text2 + " " + Dns.GetHostEntry("127.0.0.1").HostName + "\r\n";
						break;
					case 1:
						text2 = text2 + "<" + this.mailMessage.From + ">\r\n";
						break;
					case 2:
						flag2 = true;
						break;
					case 3:
						text2 += "\r\n";
						break;
					case 4:
						text2 += this.GetEmailInformation();
						break;
					case 5:
						text2 += "\r\n";
						break;
					}
					if (flag2)
					{
						if (this.mailMessage.To.Length > 0)
						{
							string[] array3 = this.mailMessage.To.Split(new char[]
							{
								',',
								';'
							});
							for (int j = 0; j < array3.Length; j++)
							{
								if (array3[j].Trim() != "")
								{
									string str = "<" + array3[j] + ">";
									text2 = "RCPT TO: " + str + "\r\n";
									this.SendDataThroughSecureStream(text2);
									if (!this.WaitForResponse("250", ref text, false))
									{
										this.errorMessage = "Server rejected the email address: " + str + ".";
										this.tcp_Socket.Close();
										this.ErrorNumber = 1;
										this.RaiseErrorEmailSent(4, this.errorMessage);
									}
								}
							}
						}
						if (this.mailMessage.CC.Length > 0)
						{
							string[] array3 = this.mailMessage.CC.Split(new char[]
							{
								',',
								';'
							});
							for (int j = 0; j < array3.Length; j++)
							{
								string str = "<" + array3[j] + ">";
								text2 = "RCPT TO: " + str + "\r\n";
								this.SendDataThroughSecureStream(text2);
								if (!this.WaitForResponse("250", ref text, false))
								{
									this.errorMessage = "Server rejected the email address: " + str + ".";
									this.tcp_Socket.Close();
									this.ErrorNumber = 1;
									this.RaiseErrorEmailSent(5, this.errorMessage);
								}
							}
						}
						if (this.mailMessage.BCC.Length > 0)
						{
							string[] array3 = this.mailMessage.BCC.Split(new char[]
							{
								',',
								';'
							});
							for (int j = 0; j < array3.Length; j++)
							{
								string str = "<" + array3[j] + ">";
								text2 = "RCPT TO: " + str + "\r\n";
								this.SendDataThroughSecureStream(text2);
								if (!this.WaitForResponse("250", ref text, false))
								{
									this.errorMessage = "Server rejected the email address: " + str + ".";
									this.tcp_Socket.Close();
									this.ErrorNumber = 1;
									this.RaiseErrorEmailSent(6, this.errorMessage);
								}
							}
						}
						flag2 = false;
					}
					else
					{
						if (i == 0)
						{
							this.SendDataThroughNetworkStream(text2);
							if (!this.WaitForResponse(array2[0], ref text, true))
							{
								this.errorMessage = string.Concat(new string[]
								{
									"Did not get ",
									array2[0],
									" reply from server for command ",
									array[0],
									".\r\nServer said: ",
									text
								});
								this.tcp_Socket.Close();
								this.ErrorNumber = 1;
								this.RaiseErrorEmailSent(7, this.errorMessage);
							}
							else
							{
								text2 = "STARTTLS\r\n";
								this.SendDataThroughNetworkStream(text2);
								if (!this.WaitForResponse("220", ref text, true))
								{
									this.errorMessage = "Did not get 220 reply from server for command STARTTLS.\r\nServer said: " + text;
									this.tcp_Socket.Close();
									this.ErrorNumber = 1;
									this.RaiseErrorEmailSent(8, this.errorMessage);
								}
								else
								{
									this.secureStream = new SslStream(this.networkStream, true, new RemoteCertificateValidationCallback(SmtpClient2.OnCertificateValidation));
									this.secureStream.AuthenticateAsClient("localhost");
									if (this.secureStream.IsAuthenticated)
									{
										text2 = "Ehlo " + Dns.GetHostEntry("127.0.0.1").HostName + "\r\n";
										this.SendDataThroughSecureStream(text2);
										if (!this.WaitForResponse(array2[0], ref text, false))
										{
											this.errorMessage = string.Concat(new string[]
											{
												"Did not get ",
												array2[0],
												" reply from server for command ",
												array[0],
												".\r\nServer said: ",
												text
											});
											this.tcp_Socket.Close();
											this.ErrorNumber = 1;
											this.RaiseErrorEmailSent(9, this.errorMessage);
										}
										else
										{
											if (text.IndexOf("Auth Login", StringComparison.OrdinalIgnoreCase) >= 0)
											{
												text2 = "Auth Login\r\n";
												this.SendDataThroughSecureStream(text2);
												if (!this.WaitForResponse("334", ref text, false))
												{
													this.errorMessage = "Did not get 334 reply from server for AUTH LOGIN.\r\nServer said: " + text;
													this.tcp_Socket.Close();
													this.ErrorNumber = 1;
													this.RaiseErrorEmailSent(10, this.errorMessage);
												}
												else
												{
													byte[] bytes = aSCIIEncoding.GetBytes(this.userName);
													text2 = Convert.ToBase64String(bytes) + "\r\n";
													this.RaiseAuthenticationBegan(this.userName);
													this.SendDataThroughSecureStream(text2);
													if (!this.WaitForResponse("334", ref text, false))
													{
														this.errorMessage = "Did not get 334 reply from server for UserName Confirmation.\r\nServer said: " + text;
														this.tcp_Socket.Close();
														this.ErrorNumber = 1;
														this.RaiseErrorEmailSent(11, this.errorMessage);
													}
													else
													{
														bytes = aSCIIEncoding.GetBytes(this.password);
														text2 = Convert.ToBase64String(bytes) + "\r\n";
														this.SendDataThroughSecureStream(text2);
														if (!this.WaitForResponse("235", ref text, false))
														{
															this.errorMessage = "Did not get 235 reply from server for Password Confirmation.\r\nServer said: " + text;
															this.tcp_Socket.Close();
															this.ErrorNumber = 1;
															this.RaiseErrorEmailSent(12, this.errorMessage);
														}
														else
														{
															this.RaiseAuthenticationFinished(this.userName);
														}
													}
												}
											}
										}
									}
								}
							}
						}
						else
						{
							if (i == 4)
							{
								this.RaiseStartedDataTransfer();
								this.SendDataThroughSecureStream(text2);
								if (!this.WaitForResponse(array2[i], ref text, false))
								{
									this.errorMessage = string.Concat(new string[]
									{
										"Did not get ",
										array2[i],
										" reply from server for command ",
										array[i],
										".\r\nServer said: ",
										text
									});
									this.tcp_Socket.Close();
									this.ErrorNumber = 1;
									this.RaiseErrorEmailSent(13, this.errorMessage);
								}
								else
								{
									this.RaiseEndedDataTransfer();
								}
							}
							else
							{
								this.SendDataThroughSecureStream(text2);
								if (!this.WaitForResponse(array2[i], ref text, false))
								{
									this.errorMessage = string.Concat(new string[]
									{
										"Did not get ",
										array2[i],
										" reply from server for command ",
										array[i],
										".\r\nServer said: ",
										text
									});
									this.tcp_Socket.Close();
									this.ErrorNumber = 1;
									this.RaiseErrorEmailSent(14, this.errorMessage);
								}
								if (i == 5)
								{
									if (this.tcp_Socket.Connected)
									{
										this.tcp_Socket.Close();
										this.RaiseDisconnected(this.smtpServer);
									}
								}
							}
						}
					}
				}
			}
			if (this.tcp_Socket.Connected)
			{
				this.tcp_Socket.Close();
				this.RaiseDisconnected(this.smtpServer);
				this.RaiseSendProcess(11, this.Maxvalue);
			}
			this.RaiseSuccesses();
			this.RaiseSendProcess(12, this.Maxvalue);
		}
		public void SendMail(string from, string recipient, string subject, string body)
		{
			this.mailMessage = new MailMessage2(from, recipient, subject, body);
			this.SendMail(this.mailMessage);
		}
		private void SendDataThroughNetworkStream(string msg)
		{
			try
			{
				byte[] bytes = Encoding.ASCII.GetBytes(msg);
				this.networkStream.Write(bytes, 0, bytes.Length);
			}
			catch (Exception ex)
			{
				this.RaiseErrorEmailSent(13, ex.Message);
			}
		}
		private void SendDataThroughSecureStream(string msg)
		{
			try
			{
				byte[] bytes = Encoding.UTF8.GetBytes(msg);
				this.secureStream.Write(bytes, 0, bytes.Length);
			}
			catch (Exception ex)
			{
				this.RaiseErrorEmailSent(14, ex.Message);
			}
		}
		private string GetEmailInformation()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("MIME-Version: 1.0\r\n");
			stringBuilder.Append("From: <" + this.mailMessage.From + ">\r\n");
			stringBuilder.Append("To: " + this.mailMessage.To + "\r\n");
			if (this.mailMessage.CC.Length > 0)
			{
				stringBuilder.Append("Cc: " + this.mailMessage.CC + "\r\n");
			}
			stringBuilder.Append("Subject: " + this.mailMessage.Subject + "\r\n");
			stringBuilder.Append("Date: " + DateTime.Now.ToString("F") + "\r\n");
			switch (this.mailMessage.MailPriority)
			{
			case MailSendPriority.HIGH:
				stringBuilder.Append("Priority: High\r\n");
				break;
			case MailSendPriority.NORMAL:
				stringBuilder.Append("Priority: Normal\r\n");
				break;
			case MailSendPriority.LOW:
				stringBuilder.Append("Priority: Low\r\n");
				break;
			}
			string str = "--boundary_0_" + Guid.NewGuid().ToString();
			if (this.mailMessage.AttachmentCount > 0)
			{
				stringBuilder.Append("Content-Type: multipart/mixed; ");
				stringBuilder.Append("boundary=\"" + str + "\"\r\n");
				stringBuilder.Append("\r\n");
				stringBuilder.Append("--" + str + "\r\n");
			}
			switch (this.mailMessage.MailType)
			{
			case MailEncodingType.PLAINTEXT:
				stringBuilder.Append("Content-Type: text/plain; ");
				break;
			case MailEncodingType.HTML:
				stringBuilder.Append("Content-Type: text/html; ");
				break;
			}
			stringBuilder.Append("charset=utf-8 \r\n");
			stringBuilder.Append("Content-Transfer-Encoding: 8bit\r\n");
			stringBuilder.Append("\r\n");
			stringBuilder.Append(this.mailMessage.Message + "\r\n\r\n");
			for (int i = 0; i < this.mailMessage.AttachmentCount; i++)
			{
				stringBuilder.Append("--" + str + "\r\n");
				Attachment attachment = new Attachment(this.mailMessage.Attachments[i].ToString());
				stringBuilder.Append(attachment.GetMimeMessage());
			}
			if (this.mailMessage.AttachmentCount > 0)
			{
				stringBuilder.Append("--" + str + "--");
			}
			stringBuilder.Append("\r\n.\r\n");
			return stringBuilder.ToString();
		}
		private string HTMLEncode(string data)
		{
			StringBuilder stringBuilder = new StringBuilder(data);
			stringBuilder.Replace("á", "&aacute;");
			stringBuilder.Replace("é", "&eacute;");
			stringBuilder.Replace("í", "&iacute;");
			stringBuilder.Replace("ó", "&oacute;");
			stringBuilder.Replace("ú", "&uacute;");
			stringBuilder.Replace("ñ", "&ntilde;");
			return stringBuilder.ToString();
		}
		private bool WaitForResponse(string responseCode, ref string responseText, bool isNetworkStream)
		{
			DateTime now = DateTime.Now;
			TimeSpan timeSpan = DateTime.Now - now;
			byte[] array = new byte[1024];
			ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();
			bool result;
			while (timeSpan.Seconds < this.timeOut)
			{
				try
				{
					if (this.networkStream.DataAvailable)
					{
						if (isNetworkStream)
						{
							int num = this.networkStream.Read(array, 0, array.Length);
						}
						else
						{
							int num = this.secureStream.Read(array, 0, array.Length);
						}
						responseText = aSCIIEncoding.GetString(array, 0, array.Length);
						if (responseText.Substring(0, responseCode.Length).Equals(responseCode))
						{
							result = true;
							return result;
						}
						result = false;
						return result;
					}
					else
					{
						timeSpan = DateTime.Now - now;
					}
				}
				catch (Exception ex)
				{
					this.RaiseErrorEmailSent(14, ex.Message);
					result = false;
					return result;
				}
			}
			result = false;
			return result;
		}
		private static bool OnCertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
		{
			return true;
		}
	}
}
